﻿using Blm.Utils.Extensions;
using Blm.Utils.Utility;
using Language.Resource;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Core.Model.Sys;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.DtoModel.Sys;
using VisionCloud.Domain.Extension;
using VisionCloud.Domain.Repository.Interface.Sys;

namespace VisionCloud.Domain.Repository.Implement.Sys
{
    public class SysUserRepository : BaseRepository<SysUser>, ISysUserRepository
    {
        public OperatorInfo _tokenModel => OperatorProvider.Get();

        public IStringLocalizer<RepositoryResource> Localizer { get; set; }

        /// <summary>
        /// 登录调用
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        public async Task<SysUserDto> FindUser(SysUserDto userDto)
        {
            SysUserCondition condition = new SysUserCondition() { UserCode = userDto.Code, UserPwd = userDto.Password.GetMD5() };
            var pageinfo = await GetPage2(condition);
            var userInfo = pageinfo.PageData as List<SysUserDto>;
            if (userInfo != null && userInfo.Count == 1)
            {
                return userInfo[0];
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 查询某个用户（只支持用户代码Code,UserId）
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        public async Task<SysUserListDto> GetUser(SysUserDto userDto)
        {
            SysUserCondition condition = new SysUserCondition() { UserCode = userDto.Code, UserId = userDto.UserId };
            var pageinfo = await GetPage2(condition);
            var userInfo = pageinfo.PageData as List<SysUserListDto>;
            if (userInfo != null && userInfo.Count == 1)
            {
                return userInfo[0];
            }
            else
            {
                return null;
            }
        }

        public async Task<ApiResult> GetCheckUser(SysUser sysUserDto)
        {
            string msg = string.Empty;
            var temp = await (from t in Db.SysUsers
                              where t.IsDeleted == false
                              select t)
                                 .FirstOrDefaultAsync(i =>
                                 (i.PhoneNumber == sysUserDto.PhoneNumber)
                                 ||
                                 (i.Email == sysUserDto.Email)
                                );

            if (temp == null || temp.IsDeleted == true)
            {
                return new ApiResult() { Code = Common.AjaxCode.Success, Result = null, Message = msg };
            }

            string wordWrap = "\r\n";

            msg += string.Format(Localizer["YB0268"].Value, sysUserDto.RowIndex) + wordWrap;
            //msg += $"第{sysUserDto.RowIndex}行数据与数据库中的重复:" + wordWrap;

            //if (temp.Name == sysUserDto.Name)
            //{
            //    msg += $"用户名称{temp.Name}已存在;" + wordWrap;
            //}

            if (temp.PhoneNumber == sysUserDto.PhoneNumber)
            {
                msg += string.Format(Localizer["YB0269"].Value, temp.PhoneNumber) + wordWrap;
                //msg += $"手机号码{ temp.PhoneNumber}已存在;" + wordWrap;
            }

            if (temp.Email == sysUserDto.Email)
            {
                msg += string.Format(Localizer["YB0270"].Value, temp.Email) + wordWrap;
                //msg += $"邮箱{temp.Email}已存在;" + wordWrap;
            }
            return new ApiResult() { Code = Common.AjaxCode.Success, Result = temp, Message = msg };
        }

        public async Task<SysUserDto> FindUserByNamePwd(SysUserDto userDto)
        {
            return Db.SysUsers.Where(p => p.Name == userDto.Name && p.Password == userDto.Password.GetMD5() && p.IsDeleted == false)
                    .Select(w => w.CopyTo<SysUserDto>()).SingleOrDefault();
        }

        public async Task<ApiPageResult> GetPage2(SysUserCondition condition)
        {
            if (condition == null)
            {
                throw new ArgumentException(Localizer["YB0271"].Value);
            }
            // 默认按照修改时间降序排序
            if (string.IsNullOrEmpty(condition.OrderBy))
            {
                condition.AscDesc = "DESC";
                condition.OrderBy = "CreatedDate";
            }

            var pageResult = GetMeasureAppData(condition);
            // 查询不到时返回null
            if (pageResult == null)
            {
                pageResult = new ApiPageResult();
            }

            condition.Total = pageResult.Total;
            return pageResult;
        }

        /// <summary>
        /// 获取测量应用的用户数据
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        private ApiPageResult GetMeasureAppData(SysUserCondition condition)
        {
            switch (_tokenModel.RoleNameList.ToString())
            {
                case "公司管理员":
                    return GetCompanyAdminUserList(condition);

                case "测量管理员":
                    return GetMeasureAdminUserList(condition);

                case "项目管理员":
                    return GetProjectAdminUserList(condition);

                case "测量员":
                    return GetMeasureUserList(condition);

                default:
                    return GetCompanyAdminUserList(condition);
            }
        }

        /// <summary>
        /// 公司管理员可以查看的用户列表
        /// </summary>
        /// <returns></returns>
        private ApiPageResult GetCompanyAdminUserList(SysUserCondition condition)
        {
            condition.CompanyGuid = _tokenModel.CompanyGuid;
            List<SysUserListDto> userList = null; //GetCompanyUseList(condition);
            var query = QueryCompanyUserList(condition);
            // 按照默认创建时间和名称排序
            if (condition.OrderBy.Contains("CreatedDate"))
            {
                userList = query.PageOrderBy(condition).ThenBy("Name")
                    .Skip((condition.CurrentPage - 1) * condition.PageSize)
                    .Take(condition.PageSize).ToList();
            }
            else
            {
                // 按照用户自定义排序
                userList = query.PageOrderBy(condition).ThenByDescending("CreatedDate")
                    .Skip((condition.CurrentPage - 1 < 0 ? 0 : condition.CurrentPage - 1) * condition.PageSize)
                    .Take(condition.PageSize).ToList();
            }

            if (userList == null || userList.Count == 0)
            {
                return null;
            }

            var userPrjList = Db.MsUserToProjects.WhereIf(userList != null, x => userList.Select(u => u.YunUserGuid).Contains(x.YunUserGuid)).ToList();

            foreach (var user in userList)
            {
                var userPrjs = userPrjList.Where(p => p.YunUserGuid == user.YunUserGuid).ToList();
                if (userPrjs != null && userPrjs.Count > 0)
                {
                    foreach (var prj in userPrjs)
                    {
                        if (user.Projects == null)
                        {
                            user.Projects = new List<DtoModel.Ms.ProjectInfoDto>();
                        }
                        user.Projects.Add(new DtoModel.Ms.ProjectInfoDto() { ProjectId = prj.YunProjectGuid });
                    }
                }
            }

            var result = condition.CopyTo<ApiPageResult>();
            result.PageData = userList;
            result.Total = query.Count();
            return result;
        }

        /// <summary>
        /// 本公司的用户信息
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        private List<SysUserListDto> GetCompanyUseList(SysUserCondition condition)
        {
            List<SysUserListDto> userList = new List<SysUserListDto>();
            var query = (from users in Db.SysUsers
                         where users.IsDeleted == false
                         where (condition.UserId == Guid.Empty || users.YunUserGuid == condition.UserId)
                         where (condition.UserType == null || (users.UserType == condition.UserType || users.RoleNameList.IndexOf("公司管理员") > -1))
                         where (condition.Status == null || users.Status == condition.Status)
                         where (condition.CompanyGuid == Guid.Empty || users.SysOrgId == condition.CompanyGuid.ToString())
                         where (condition.Department == null || users.Department == condition.Department)
                         where (condition.RoleName == null || users.RoleNameList.IndexOf(condition.RoleName) > -1)
                         where (string.IsNullOrEmpty(condition.UserName) || users.Name.Contains(condition.UserName))
                         where (condition.UserCode == null || users.Name == condition.UserCode || users.PhoneNumber == condition.UserCode)//手机号也可以当登录处理
                         where (condition.Content == null
                         || users.Name.Contains(condition.Content)
                         || users.PhoneNumber.Contains(condition.Content)
                         || users.Email.Contains(condition.Content)
                         || users.Department.Contains(condition.Content)
                         || users.RoleNameList.Contains(condition.Content)
                         || users.Status.ToString() == condition.Content
                         )
                         select new
                         {
                             SysUserListDto = users.CopyTo<SysUserListDto>(),
                         }
                    );

            var userRoleList = query.ToList();
            foreach (var user in userRoleList)
            {
                userList.Add(user.SysUserListDto);
            }

            return userList;
        }

        /// <summary>
        /// 查询本公司的用户信息
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        private IQueryable<SysUserListDto> QueryCompanyUserList(SysUserCondition condition, List<Guid> userIds = null)
        {
            //IQueryable<SysUserListDto> query = null;
            //query = (from users in Db.SysUsers
            //         where users.IsDeleted == false
            //         where (condition.CompanyGuid == Guid.Empty || users.SysOrgId == condition.CompanyGuid.ToString())
            //         where (condition.UserId == Guid.Empty || users.YunUserGuid == condition.UserId)
            //         where (userIds == null || userIds.Contains(users.YunUserGuid))
            //         where (condition.UserType == null || (users.UserType == condition.UserType || users.RoleNameList.IndexOf("公司管理员") > -1))
            //         where (condition.Status == null || users.Status == condition.Status)
            //         where (condition.Department == null || users.Department == condition.Department)
            //         where (condition.RoleName == null || users.RoleNameList.IndexOf(condition.RoleName) > -1)
            //         where (string.IsNullOrEmpty(condition.UserName) || users.Name.Contains(condition.UserName))
            //         where (condition.UserCode == null || users.Name == condition.UserCode || users.PhoneNumber == condition.UserCode)//手机号也可以当登录处理
            //         where (string.IsNullOrWhiteSpace( condition.Content)
            //         || users.Name.Contains(condition.Content)
            //         || users.PhoneNumber.Contains(condition.Content)
            //         || users.Email.Contains(condition.Content)
            //         || users.Department.Contains(condition.Content)
            //         || users.RoleNameList.Contains(condition.Content)
            //         || users.Status.ToString() == condition.Content
            //         )
            //         select new SysUserListDto
            //         {
            //             Name = users.Name,
            //             YunUserGuid = users.YunUserGuid,
            //             PhoneNumber = users.PhoneNumber,
            //             Email = users.Email,
            //             Status = users.Status,
            //             Position = users.Position,
            //             Department = users.Department,
            //             AccountNumber = users.AccountNumber,
            //             RoleNameList = users.RoleNameList,
            //             SysOrgId = users.SysOrgId,
            //         }
            //        );
            return Db.SysUsers.Where(a => !a.IsDeleted).WhereIf(condition.CompanyGuid != Guid.Empty, b => b.SysOrgId == condition.CompanyGuid.ToString())
                .WhereIf(condition.UserId != Guid.Empty, c => c.YunUserGuid == condition.UserId)
                .WhereIf(userIds != null, d => userIds.Contains(d.YunUserGuid))
                .WhereIf(condition.UserType != null, e => e.UserType == condition.UserType || e.RoleNameList.IndexOf("公司管理员") > -1)
                .WhereIf(condition.Status != null, f => f.Status == condition.Status)
                .WhereIf(condition.Department != null, h => h.Department == condition.Department)
                .WhereIf(condition.RoleName != null, j => j.RoleNameList.IndexOf(condition.RoleName) > -1)
                .WhereIf(!string.IsNullOrEmpty(condition.UserName), k => k.Name.Contains(condition.UserName))
                .WhereIf(condition.UserCode != null, m => m.Name == condition.UserCode || m.PhoneNumber == condition.UserCode)
                .WhereIf(!string.IsNullOrWhiteSpace(condition.Content), x => x.Name.Contains(condition.Content)
                      || x.PhoneNumber.Contains(condition.Content)
                      || x.Email.Contains(condition.Content)
                      || x.Department.Contains(condition.Content)
                      || x.RoleNameList.Contains(condition.Content)
                      || ((string)(object)x.Status).Contains(condition.Content)
                      )
                .Select(z => new SysUserListDto
                {
                    Name = z.Name,
                    YunUserGuid = z.YunUserGuid,
                    PhoneNumber = z.PhoneNumber,
                    Email = z.Email,
                    Status = z.Status,
                    Position = z.Position,
                    Department = z.Department,
                    AccountNumber = z.AccountNumber,
                    RoleNameList = z.RoleNameList,
                    SysOrgId = z.SysOrgId,
                    LastUpdatedDate = z.LastUpdatedDate,
                    CreatedDate = z.CreatedDate
                });
            //return query;
        }

        /// <summary>
        /// 本公司的用户信息
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public async Task<List<SysUserListDto>> GetCompanyUseListAsync(SysUserCondition condition)
        {
            List<SysUserListDto> userList = new List<SysUserListDto>();
            var query = (from users in Db.SysUsers
                         where users.IsDeleted == false
                         where (condition.UserId == Guid.Empty || users.YunUserGuid == condition.UserId)
                         where (condition.UserType == null || (users.UserType == condition.UserType || users.RoleNameList.IndexOf("公司管理员") > -1))
                         where (condition.Status == null || users.Status == condition.Status)
                         where (condition.CompanyGuid == Guid.Empty || users.SysOrgId == condition.CompanyGuid.ToString())
                         where (condition.Department == null || users.Department == condition.Department)
                         where (condition.RoleName == null || users.RoleNameList.IndexOf(condition.RoleName) > -1)
                         where (string.IsNullOrEmpty(condition.UserName) || users.Name.Contains(condition.UserName))
                         where (condition.UserCode == null || users.Name == condition.UserCode || users.PhoneNumber == condition.UserCode)//手机号也可以当登录处理
                         where (condition.Content == null
                         || users.Name.Contains(condition.Content)
                         || users.PhoneNumber.Contains(condition.Content)
                         || users.Email.Contains(condition.Content)
                         || users.Department.Contains(condition.Content)
                         || users.RoleNameList.Contains(condition.Content)
                         || users.Status.ToString() == condition.Content
                         )
                         where (users.IsDeleted == false)
                         select new
                         {
                             SysUserListDto = users.CopyTo<SysUserListDto>(),
                         }
                    );
            var userRoleList = await query.AsNoTracking().ToListAsync().ConfigureAwait(false);
            foreach (var user in userRoleList)
            {
                userList.Add(user.SysUserListDto);
            }

            return userList;
        }

        /// <summary>
        /// 测量管理员可以查看的用户列表:同一个公司的同一个项目里的的测量管理员、项目管理员、测量员
        /// </summary>
        /// <returns></returns>
        private ApiPageResult GetMeasureAdminUserList(SysUserCondition condition)
        {
            condition.CompanyGuid = _tokenModel.CompanyGuid;
            //List<SysUserListDto> userList = GetCompanyUseList(condition);
            //userList = FilterProjectUser(userList);
            // 获取和当前登录用户有项目关联所有用户Id
            var temp = FilterProjectUser();
            var query = QueryCompanyUserList(condition, temp);
            List<SysUserListDto> userList = null;
            if (condition.OrderBy.Contains("CreatedDate"))
            {
                userList = query.PageOrderBy(condition).Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();
            }
            else
            {
                userList = query.PageOrderBy(condition).ThenByDescending("CreatedDate").Skip((condition.CurrentPage > 0 ? condition.CurrentPage - 1 : 0) * condition.PageSize).Take(condition.PageSize).ToList();
            }

            GetUserProject(userList);
            ApiPageResult pageResult = new ApiPageResult()
            {
                PageData = userList,
                Total = query.Count(),
            };
            return pageResult;
        }

        /// <summary>
        /// 从userList中过滤掉没有项目关系的用户(但不过滤自己)
        /// </summary>
        /// <returns></returns>
        private List<Guid> FilterProjectUser()
        {
            List<Guid> resultList = null;
            string sql = $"select DISTINCT \"UserId1\" from \"vw_project_user_relation\" where \"YunUserGuid\"='{_tokenModel.YunUserGuid}'";
            using (var ds = Db.GetDataSet(System.Data.CommandType.Text, sql))
            {
                if (ds != null && ds.Tables[0].Rows.Count > 0)
                {
                    DataTable dt = ds.Tables[0];
                    resultList = new List<Guid>();
                    foreach (DataRow dr in dt.Rows)
                    {
                        resultList.Add(dr[0].ToGuid());
                    }
                }
            }

            return resultList;
        }

        /// <summary>
        /// 获取用户的项目
        /// </summary>
        /// <param name="userList"></param>
        private void GetUserProject(List<SysUserListDto> userList)
        {
            //var userPrjList = (from userPrj in Db.MsUserToProjects
            //                   select userPrj).ToList();
            var userPrjList = Db.MsUserToProjects.Where(x => userList == null || userList.Select(u => u.YunUserGuid).Contains(x.YunUserGuid)).ToList();

            foreach (var user in userList)
            {
                var userPrjs = userPrjList.Where(p => p.YunUserGuid == user.YunUserGuid).ToList();
                if (userPrjs != null && userPrjs.Count > 0)
                {
                    foreach (var prj in userPrjs)
                    {
                        if (user.Projects == null)
                        {
                            user.Projects = new List<DtoModel.Ms.ProjectInfoDto>();
                        }
                        user.Projects.Add(new DtoModel.Ms.ProjectInfoDto() { ProjectId = prj.YunProjectGuid });
                    }
                }
            }
        }

        /// <summary>
        /// 项目管理员可以查看的用户列表:同一个公司的同一个项目里的的测量管理员、项目管理员、测量员
        /// </summary>
        /// <returns></returns>
        private ApiPageResult GetProjectAdminUserList(SysUserCondition condition)
        {
            condition.CompanyGuid = _tokenModel.CompanyGuid;
            //List<SysUserListDto> userList = GetCompanyUseList(condition);
            //userList = FilterProjectUser(userList);

            // 获取和当前登录用户有项目关联所有用户Id
            var temp = FilterProjectUser();
            var query = QueryCompanyUserList(condition, temp);
            List<SysUserListDto> userList = null;
            // 默认创建时间降序排序
            if (condition.OrderBy.Contains("CreatedDate"))
            {
                userList = query.PageOrderBy(condition).Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();
            }
            else
            {
                userList = query.PageOrderBy(condition).ThenByDescending("CreatedDate").Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();
            }

            GetUserProject(userList);
            ApiPageResult pageResult = new ApiPageResult()
            {
                PageData = userList,
                Total = query.Count(),
            };

            return pageResult;
        }

        /// <summary>
        /// 测量员可以查看的用户列表:同一个公司的同一个项目里的的测量管理员、项目管理员、测量员
        /// </summary>
        /// <returns></returns>
        private ApiPageResult GetMeasureUserList(SysUserCondition condition)
        {
            condition.CompanyGuid = _tokenModel.CompanyGuid;
            //List<SysUserListDto> userList = GetCompanyUseList(condition);
            //userList = FilterProjectUser(userList);

            // 获取和当前登录用户有项目关联所有用户Id
            var temp = FilterProjectUser();
            var query = QueryCompanyUserList(condition, temp);
            //var userList = query.PageOrderBy(condition).Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();

            List<SysUserListDto> userList = null;
            // 默认用户创建时间降序排序
            if (condition.OrderBy.Contains("CreatedDate"))
            {
                userList = query.PageOrderBy(condition).Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();
            }
            else
            {
                userList = query.PageOrderBy(condition).ThenByDescending("CreatedDate").Skip((condition.CurrentPage - 1) * condition.PageSize).Take(condition.PageSize).ToList();
            }

            GetUserProject(userList);
            ApiPageResult pageResult = new ApiPageResult()
            {
                PageData = userList,
                Total = query.Count(),
            };
            return pageResult;
        }

        /// <summary>
        /// 获取注册的用户设备数量
        /// </summary>
        /// <returns></returns>
        public async Task<int> GetRegistedUserCount()
        {
            try
            {
                return await Db.SysDevices
                    .Where(i => i.IsDeleted == false)
                    .CountAsync()
                    .ConfigureAwait(false);
            }
            catch
            {
                return 0;
            }
        }

        public async Task<DogUserDto> GetDogUser(RegisterDto registerDto)
        {
            List<DogUserDto> list = new List<DogUserDto>();
            string sql = $"select * from vw_userinfo where \"EncryptedDogNumber\"='{registerDto.EncryptedDogNumber}' and \"EncryptedDogType\"='{registerDto.EncryptedDogType}' ";
            using (var ds = Db.GetDataSet(System.Data.CommandType.Text, sql))
            {
                if (ds != null && ds.Tables[0].Rows.Count > 0)
                {
                    var dr = ds.Tables[0].Rows[0];
                    DogUserDto model = new DogUserDto();
                    model.AccountNumber = dr["AccountNumber"].NullToString();
                    model.Email = dr["Email"].NullToString();
                    model.Name = dr["Name"].NullToString();
                    model.DeviceGuid = dr["DeviceGuid"].NullToString();
                    model.YunUserGuid = dr["YunUserGuid"].NullToString();
                    model.EncryptedDogType = dr["EncryptedDogType"].NullToString();
                    model.EncryptedDogNumber = dr["EncryptedDogNumber"].NullToString();
                    model.IsActive = dr["IsActive"].NullToString();
                    model.ActiveDate = dr["ActiveDate"].NullToString();
                    model.Password = dr["Password"].NullToString();
                    return model;
                }
            }
            return null;
        }

        /// <summary>
        /// 项目测量员
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<List<DogUserDto>> GetProjectMeasureMan(DeviceProjectDto dto)
        {
            List<DogUserDto> list = new List<DogUserDto>();
            //#if DEBUG
            //            string sql = "select t.\"YunUserGuid\",t.\"Name\" from \"SysUser\" t where  t.\"RoleNameList\" like '%人工测量员%';";

            //#else
            //            string sql = $"SELECT t1.\"YunUserGuid\",t1.\"Name\" FROM \"vw_userinfo\" t1 JOIN \"MsUserToProject\" t2 ON t2.\"YunUserGuid\" = t1.\"YunUserGuid\" where t1.\"DeviceGuid\"='{dto.DeviceGuid}' and t2.\"YunProjectGuid\"='{dto.ProjectId}';";
            //#endif

            //string sql = $"SELECT t1.\"YunUserGuid\",t1.\"Name\" FROM \"vw_userinfo\" t1 JOIN \"MsUserToProject\" t2 ON t2.\"YunUserGuid\" = t1.\"YunUserGuid\" where   t2.\"YunProjectGuid\"='{dto.ProjectId}';";

            string sql = $"SELECT  t1.\"YunUserGuid\",t1.\"Name\" FROM \"SysUser\" t1 LEFT JOIN \"MsUserToProject\" t2 ON t1.\"YunUserGuid\" = t2.\"YunUserGuid\" WHERE t2.\"YunProjectGuid\" ='{dto.ProjectId}'  AND \"IsDeleted\" = FALSE AND t1.\"RoleNameList\" LIKE'%人工%'";
            using (var ds = Db.GetDataSet(System.Data.CommandType.Text, sql))
            {
                if (ds != null && ds.Tables[0].Rows.Count > 0)
                {
                    foreach (DataRow dr in ds.Tables[0].Rows)
                    {
                        DogUserDto model = new DogUserDto();
                        model.Name = dr["Name"].NullToString();
                        model.YunUserGuid = dr["YunUserGuid"].NullToString();
                        list.Add(model);
                    }
                }
            }

            return list;
        }
    }
}